package org.example.btchat.client;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;

import org.example.btchat.BTChat;
import org.example.btchat.BTChatInterface;
import org.example.btchat.MainActivity;
import org.example.btchat.Message;
import org.example.btchat.R;

import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.widget.Toast;

public class ClientService extends Service implements BTChatInterface
{
	public class LocalBinder extends Binder
	{
		public ClientService getService()
		{
			return ClientService.this;
		}
	}
	
	private MainActivity activity;
	private BluetoothAdapter adapter;
	private String address;
	private BluetoothSocket client;
	private BluetoothDevice device;
	private InputStream input;
	private ArrayList<Message> messages = new ArrayList<Message>();
	private OutputStream output;
	
	@SuppressWarnings("unused")
	private Thread thread;
	
	@Override
	public String getName()
	{
		return adapter.getName();
	}
	
	@Override
	public void onActivityResult(int requestCode, int resultCode, Intent data)
	{
	}
	
	@Override
	public IBinder onBind(Intent intent)
	{
		address = intent.getStringExtra("device");
		
		return new LocalBinder();
	}
	
	@Override
	public synchronized void sendMessage(Message msg)
	{
		try
		{
			output.write(msg.getSource().getBytes());
			output.write("\0".getBytes());
			output.write(msg.getMessage().getBytes());
			output.write("\0\0".getBytes());
		}
		catch(IOException e)
		{
			Toast.makeText(
				this,
				getString(R.string.msg_lost_connection, device.getName()),
				Toast.LENGTH_SHORT).show();
			stopSelf();
		}
	}
	
	@Override
	public void setActivity(MainActivity activity)
	{
		this.activity = activity;
	}
	
	@Override
	public void start() throws Exception
	{
		adapter = BluetoothAdapter.getDefaultAdapter();
		
		if(adapter == null)
		{
			Toast.makeText(this, getString(R.string.msg_no_bluetooth), Toast.LENGTH_LONG).show();
			stopSelf();
			return;
		}
		
		if(adapter.isEnabled())
		{
			startClient();
		}
		else
		{
			startActivityForResult(new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE),
				BTChat.REQUEST_ENABLE_BT);
		}
	}
	
	private void onMessageSent(final Message msg)
	{
		messages.add(msg);
		
		activity.runOnUiThread(new Runnable()
		{
			@Override
			public void run()
			{
				activity.onMessageReceive(msg);
			}
		});
	}
	
	private void parse(String buffer)
	{
		int pos = buffer.indexOf("\0");
		if(pos == -1)
			return;
		
		String source = buffer.substring(0, pos);
		String message = buffer.substring(pos + 1);
		
		onMessageSent(new Message(source, message));
	}
	
	private void startActivityForResult(Intent intent, int requestCode) throws Exception
	{
		if(activity != null)
			activity.startActivityForResult(intent, requestCode);
		else
			throw new Exception("No activity set to interact!");
	}
	
	private void startClient() throws IOException
	{
		device = adapter.getRemoteDevice(this.address);
		
		try
		{
			client = device.createRfcommSocketToServiceRecord(BTChat.MY_UUID);
			output = client.getOutputStream();
			input = client.getInputStream();
		}
		catch(IOException e)
		{
			Toast.makeText(this, getString(R.string.msg_no_connection), Toast.LENGTH_LONG).show();
			throw e;
		}
		
		thread = new Thread(new Runnable()
		{
			@Override
			public void run()
			{
				try
				{
					read();
				}
				catch(IOException e)
				{
					activity.runOnUiThread(new Runnable()
					{
						@Override
						public void run()
						{
							stopSelf();
						}
					});
				}
			}
		});
	}
	
	protected void read() throws IOException
	{
		int pos;
		byte[] read = new byte[1];
		String buffer = "";
		
		while(true)
		{
			read[0] = (byte) input.read();
			buffer += read;
			
			pos = buffer.indexOf("\0\0");
			if(pos != -1)
			{
				parse(buffer.substring(0, pos));
				buffer = buffer.substring(pos + 2);
			}
		}
	}
}
